/*
 * Decompiled with CFR 0.150.
 * 
 * Could not load the following classes:
 *  cn.hutool.core.util.ObjectUtil
 *  javafx.application.Platform
 *  javafx.fxml.FXML
 *  javafx.fxml.FXMLLoader
 *  javafx.fxml.Initializable
 *  javafx.scene.Node
 *  javafx.scene.control.ListView
 *  javafx.scene.control.TableView
 *  javafx.scene.control.TextField
 *  javafx.scene.layout.HBox
 *  javafx.stage.Popup
 *  javafx.stage.Window
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.gys.common.plugIn.searchTextField;

import cn.hutool.core.util.ObjectUtil;
import com.gys.common.util.CommonUtil;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.stage.Popup;
import javafx.stage.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SearchTextField
extends HBox
implements Initializable {
    private static final Logger log = LoggerFactory.getLogger(SearchTextField.class);
    @FXML
    private TextField textField;
    private ListView<String> listview;
    private final Popup popupContainer;
    private InstantSearch<String> instantSearch;
    private Object data;
    private String property;
    private String defaultValue;
    private Map<String, Object> otherMap;
    private List<String> otherCloum;
    private TableView tableView;
    private List<TextField> textFieldForm;
    private List<String> words;
    private boolean clickFlag;

    public void initialize(URL location, ResourceBundle resources) {
        this.popupContainer.getContent().add(this.listview);
        this.popupContainer.autoHideProperty().set(true);
        this.popupContainer.hide();
        this.textField.setText(this.defaultValue);
        this.textField.textProperty().addListener((observable, oldValue, newValue) -> {
            final String trimed = newValue;
            this.showPopup((Node)this);
            Platform.runLater((Runnable)new Runnable(){

                @Override
                public void run() {
                    SearchTextField.this.doSearch(trimed);
                }
            });
        });
        this.listview.getSelectionModel().selectedItemProperty().addListener((ov, old_val, new_val) -> {
            if (ObjectUtil.isEmpty(new_val)) {
                return;
            }
            if (!this.words.contains(new_val)) {
                return;
            }
            this.textField.setText(new_val);
            if (ObjectUtil.isNotEmpty(this.data) && ObjectUtil.isNotEmpty(this.property)) {
                this.changeTableData((String)new_val);
            } else if (ObjectUtil.isNotEmpty(this.textFieldForm)) {
                this.changeFormData((String)new_val);
            }
            this.popupContainer.hide();
        });
    }

    public void setTextFieldPrefHeight(double height) {
        this.textField.setPrefHeight(height);
    }

    public void setTextFieldPrefWeight(double weight) {
        this.textField.setPrefWidth(weight);
    }

    private void changeFormData(String new_val) {
        if (!this.words.contains(new_val)) {
            return;
        }
        Object object = null;
        if ("".equals(new_val)) {
            object = "";
        } else {
            object = this.otherMap.get(new_val);
            if (ObjectUtil.isEmpty(object)) {
                return;
            }
        }
        String methodName = "";
        try {
            for (TextField cloum : this.textFieldForm) {
                String value = "";
                if (ObjectUtil.isNotEmpty(object)) {
                    if (object instanceof String) {
                        value = String.valueOf(object);
                    } else {
                        methodName = CommonUtil.getGetMethod(cloum.getId());
                        Method methodClum = object.getClass().getMethod(methodName, new Class[0]);
                        value = (String)methodClum.invoke(object, new Object[0]);
                    }
                }
                cloum.setText(value);
            }
        }
        catch (Exception ex) {
            throw new RuntimeException(methodName + "\u6ca1\u6709get\u65b9\u6cd5");
        }
    }

    private void changeTableData(String new_val) {
        try {
            Method method = this.data.getClass().getMethod(CommonUtil.getSetMethod(this.property), String.class);
            method.invoke(this.data, new_val);
            Object object = this.otherMap.get(new_val);
            if (ObjectUtil.isEmpty(this.otherCloum)) {
                return;
            }
            for (String cloum : this.otherCloum) {
                Method methodClum;
                String value = "";
                if (ObjectUtil.isNotEmpty(object)) {
                    if (object instanceof String) {
                        value = String.valueOf(object);
                    } else {
                        methodClum = object.getClass().getMethod(CommonUtil.getGetMethod(cloum), new Class[0]);
                        value = (String)methodClum.invoke(object, new Object[0]);
                    }
                }
                methodClum = this.data.getClass().getMethod(CommonUtil.getSetMethod(cloum), String.class);
                methodClum.invoke(this.data, value);
            }
            this.tableView.refresh();
        }
        catch (Exception ex) {
            throw new RuntimeException("\u6ca1\u6709\u5bf9\u5e94\u65b9\u6cd5");
        }
    }

    private void showPopup(Node parent) {
        Window window = this.textField.getScene().getWindow();
        double x = window.getX() + this.textField.localToScene(0.0, 0.0).getX() + this.textField.getScene().getX();
        double y = window.getY() + this.textField.localToScene(0.0, 0.0).getY() + this.textField.getScene().getY() + this.textField.getHeight();
        this.popupContainer.show((Node)this.getParent(), x, y);
    }

    public void setText(String value) {
        this.textField.setText(value);
    }

    public String getText() {
        return this.textField.getText();
    }

    public SearchTextField() {
        this(null, null, null, null, null, null, null);
    }

    public SearchTextField(List<String> words) {
        this(null, null, words, null, null, null, null);
    }

    public SearchTextField(Object data, String property, List<String> words, String defaultValue) {
        this(data, property, words, defaultValue, null, null, null);
    }

    public SearchTextField(Object data, String property, List<String> words, String defaultValue, Map<String, Object> otherMap, List<String> otherCloum, TableView tableView) {
        this(data, property, words, defaultValue, otherMap, otherCloum, tableView, null);
    }

    public SearchTextField(Object data, String property, List<String> words, String defaultValue, Map<String, Object> otherMap, List<String> otherCloum, TableView tableView, List<TextField> textFieldForm) {
        this.data = data;
        this.property = property;
        this.defaultValue = defaultValue;
        this.tableView = tableView;
        this.otherMap = otherMap;
        this.otherCloum = otherCloum;
        this.words = words;
        this.textFieldForm = textFieldForm;
        this.listview = new ListView();
        this.listview.setPrefHeight(90.0);
        this.listview.setPrefWidth(120.0);
        this.instantSearch = new InstantSearch<String>(words, String::contains);
        this.popupContainer = new Popup();
        URL url = SearchTextField.class.getClass().getResource("/fxml/searchTextField/searchTextField.fxml");
        FXMLLoader fxmlLoader = new FXMLLoader();
        try {
            fxmlLoader = new FXMLLoader(url);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        }
        catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    public void reLoadTextField(List<String> words, Map<String, Object> otherMap, List<TextField> textFieldForm) {
        this.otherMap = otherMap;
        this.textFieldForm = textFieldForm;
        this.words = words;
        this.instantSearch.reLoadParam(words, String::contains);
    }

    private void doSearch(String keyword) {
        if (ObjectUtil.isEmpty(keyword)) {
            this.listview.getItems().clear();
            return;
        }
        List<String> searchResult = this.instantSearch.search(keyword);
        if (this.listview == null) {
            return;
        }
        this.listview.getItems().clear();
        this.listview.setStyle("");
        if (ObjectUtil.isEmpty(searchResult)) {
            this.listview.setStyle("-fx-border-color: red;");
        }
        this.listview.getItems().addAll(searchResult);
    }

    private ListView<String> listView() {
        return new ListView();
    }

    private class InstantSearch<T> {
        private Collection<T> tCollection;
        private BiFunction<T, String, Boolean> matcher;

        public InstantSearch(Collection<T> tCollection, BiFunction<T, String, Boolean> matcher) {
            this.tCollection = tCollection;
            this.matcher = matcher;
        }

        public void reLoadParam(Collection<T> tCollection, BiFunction<T, String, Boolean> matcher) {
            this.tCollection = tCollection;
            this.matcher = matcher;
        }

        public List<T> search(String keyword) {
            return this.tCollection == null || this.matcher == null ? Collections.emptyList() : this.tCollection.stream().filter(t -> this.matcher.apply(t, keyword)).collect(Collectors.toList());
        }
    }
}

